Skip to content

Conversation

dmarek-flex
Copy link
Contributor

@dmarek-flex dmarek-flex commented Sep 23, 2025

add a ImpedanceSpec for controlling how characteristic impedance is calculated from modes

backend PR: https://github.com/flexcompute/compute/pull/2497

- [ ] Finalize docs including the new Microwave components somewhere (monitors/mode_specs/path_specs)
Now tracking here

  • Implement more precise mode plane bounds calculation raised by @dbochkov-flexcompute
  • Support ModeSimulation

Greptile Overview

Updated On: 2025-10-07 20:11:19 UTC

Summary

This PR introduces a comprehensive impedance calculation system for microwave mode solvers in Tidy3D. The implementation adds the ability to calculate characteristic impedance from electromagnetic modes, which is essential for microwave and RF transmission line analysis.

Key architectural changes:

  • New impedance specification system: Introduces ImpedanceSpecTypes union with AutoImpedanceSpec for automatic impedance calculation and CustomImpedanceSpec for user-defined voltage/current path integrals
  • Microwave mode specifications: Adds MicrowaveModeSpec extending the base mode specification with impedance calculation capabilities for each mode
  • Enhanced mode solver integration: Extends ModeSpec, ModeSolver, and related classes to support microwave specifications while maintaining backward compatibility
  • Path integral infrastructure: Comprehensive system for voltage and current path integral specifications including axis-aligned, custom 2D, and composite current integrals
  • New monitor types: Adds MicrowaveModeMonitor and MicrowaveModeSolverMonitor for microwave-specific data collection
  • Data extensions: New MicrowaveModeData and MicrowaveModeSolverData classes that include transmission line characteristics (impedance, voltage/current coefficients)

Implementation highlights:

  • Mode plane analysis: Automatic conductor detection and path generation for simple geometries through ModePlaneAnalyzer
  • Flexible impedance calculation: Supports both direct calculation (when voltage and current integrals are available) and fallback methods using power flux
  • Comprehensive validation: Multi-level validation ensures proper setup before expensive simulation runs
  • Clean refactoring: Established microwave component hierarchy with MicrowaveBaseModel base class for consistent RF licensing and functionality
  • API consistency improvements: Standardized naming conventions for path integral classes (e.g., VoltageIntegralAxisAlignedAxisAlignedVoltageIntegral)

The system integrates seamlessly with existing Tidy3D workflows - users can continue using standard mode specifications for basic electromagnetic analysis while accessing advanced impedance calculations through the new microwave specifications. The architecture properly separates automatic impedance calculation for common cases from custom path integral specifications for complex geometries.

PR Description Notes:

  • The PR description references an incomplete checklist item about finalizing documentation, but the migration guide and API documentation appear comprehensive

Important Files Changed

Changed Files
Filename Score Overview
tidy3d/components/microwave/path_integrals/impedance_spec.py 4/5 New impedance specification system with Auto and Custom variants, comprehensive validation
tidy3d/components/microwave/microwave_mode_spec.py 5/5 Clean microwave mode specification implementation with proper caching and validation
tidy3d/plugins/microwave/impedance_calculator.py 4/5 Core impedance calculator with voltage/current integral support, minor style improvements needed
tidy3d/components/mode_spec.py 3/5 Contains syntax error in validation message that needs fixing
tidy3d/components/microwave/path_integrals/mode_plane_analyzer.py 4/5 Sophisticated conductor analysis for automatic impedance calculation
tidy3d/components/mode/mode_solver.py 4/5 Major extension to support microwave impedance calculations while maintaining compatibility
tidy3d/components/microwave/path_integrals/base_spec.py 5/5 Well-designed base classes for path integral specifications
tidy3d/components/microwave/path_integrals/voltage_spec.py 4/5 Voltage path integral specifications with minor spelling error in docstring
tidy3d/components/microwave/path_integrals/current_spec.py 5/5 Comprehensive current path integral specifications including composite support
tidy3d/components/microwave/monitor.py 5/5 Clean microwave monitor implementations extending existing monitors
tidy3d/components/microwave/data/monitor_data.py 5/5 Well-structured microwave data classes with proper inheritance
tidy3d/components/microwave/base.py 5/5 Clean base class for microwave components with RF licensing warnings
tidy3d/components/simulation.py 4/5 Added microwave mode specification validation with proper error handling
tidy3d/components/geometry/utils.py 4/5 Enhanced geometry utilities with new snapping behaviors and flattening functions
tidy3d/plugins/microwave/path_integrals.py 4/5 Refactored path integral execution classes following spec/execution separation
tidy3d/plugins/microwave/custom_path_integrals.py 4/5 Complex custom path integrals with phase analysis and composite current support
docs/api/microwave/microwave_migration.rst 5/5 Comprehensive migration guide for API changes
tidy3d/__init__.py 5/5 Clean addition of microwave components to public API
CHANGELOG.md 4/5 Comprehensive changelog entries with minor duplicate entry cleanup needed
Multiple schema files 5/5 Properly updated JSON schemas for all new microwave components

Confidence score: 3/5

  • This PR requires careful review due to a syntax error that will cause runtime failures
  • Score lowered due to syntax error in validation message and extensive scope of changes requiring thorough testing
  • Pay close attention to tidy3d/components/mode_spec.py for the missing closing quote in the validation error message

Context used:

Rule from dashboard - Do not use markdown formatting in exception or warning messages; use single quotes to highlight vari... (source)
Rule from dashboard - Update the CHANGELOG.md file when making changes that affect user-facing functionality or fix bugs. (source)

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

28 files reviewed, 2 comments

Edit Code Review Bot Settings | Greptile

@dmarek-flex dmarek-flex force-pushed the dmarek/add_impedance_to_mode_data branch 2 times, most recently from ceccb9e to 18ced37 Compare September 23, 2025 19:21
@dmarek-flex dmarek-flex linked an issue Sep 23, 2025 that may be closed by this pull request
@dmarek-flex dmarek-flex self-assigned this Sep 23, 2025
@dmarek-flex dmarek-flex added the RF label Sep 23, 2025
Copy link
Contributor

github-actions bot commented Sep 24, 2025

Diff Coverage

Diff: origin/develop...HEAD, staged and unstaged changes

  • tidy3d/init.py (100%)
  • tidy3d/components/boundary.py (100%)
  • tidy3d/components/data/data_array.py (100%)
  • tidy3d/components/data/monitor_data.py (100%)
  • tidy3d/components/data/sim_data.py (100%)
  • tidy3d/components/eme/simulation.py (100%)
  • tidy3d/components/geometry/utils.py (98.0%): Missing lines 657
  • tidy3d/components/lumped_element.py (100%)
  • tidy3d/components/microwave/base.py (95.2%): Missing lines 22
  • tidy3d/components/microwave/data/dataset.py (100%)
  • tidy3d/components/microwave/data/monitor_data.py (100%)
  • tidy3d/components/microwave/impedance_calculator.py (100%)
  • tidy3d/components/microwave/mode_spec.py (100%)
  • tidy3d/components/microwave/monitor.py (100%)
  • tidy3d/components/microwave/path_integrals/factory.py (96.5%): Missing lines 132-133
  • tidy3d/components/microwave/path_integrals/integrals/auto.py (100%)
  • tidy3d/components/microwave/path_integrals/integrals/base.py (98.8%): Missing lines 47
  • tidy3d/components/microwave/path_integrals/integrals/current.py (99.2%): Missing lines 195
  • tidy3d/components/microwave/path_integrals/integrals/voltage.py (100%)
  • tidy3d/components/microwave/path_integrals/mode_plane_analyzer.py (100%)
  • tidy3d/components/microwave/path_integrals/specs/base.py (100%)
  • tidy3d/components/microwave/path_integrals/specs/current.py (100%)
  • tidy3d/components/microwave/path_integrals/specs/impedance.py (100%)
  • tidy3d/components/microwave/path_integrals/specs/voltage.py (100%)
  • tidy3d/components/microwave/path_integrals/types.py (100%)
  • tidy3d/components/microwave/path_integrals/viz.py (100%)
  • tidy3d/components/mode/data/sim_data.py (100%)
  • tidy3d/components/mode/mode_solver.py (96.6%): Missing lines 1389,2029
  • tidy3d/components/mode/simulation.py (100%)
  • tidy3d/components/mode_spec.py (100%)
  • tidy3d/components/monitor.py (100%)
  • tidy3d/components/simulation.py (100%)
  • tidy3d/components/source/field.py (100%)
  • tidy3d/components/types/mode_spec.py (100%)
  • tidy3d/components/types/monitor.py (100%)
  • tidy3d/components/types/monitor_data.py (100%)
  • tidy3d/components/types/simulation.py (100%)
  • tidy3d/config.py (100%)
  • tidy3d/plugins/microwave/init.py (100%)
  • tidy3d/plugins/microwave/array_factor.py (100%)
  • tidy3d/plugins/microwave/auto_path_integrals.py (0.0%): Missing lines 5,9
  • tidy3d/plugins/microwave/custom_path_integrals.py (0.0%): Missing lines 5,13,16,20,24
  • tidy3d/plugins/microwave/impedance_calculator.py (0.0%): Missing lines 5,11
  • tidy3d/plugins/microwave/lobe_measurer.py (100%)
  • tidy3d/plugins/microwave/path_integrals.py (0.0%): Missing lines 5,10,13,17
  • tidy3d/plugins/smatrix/component_modelers/base.py (100%)
  • tidy3d/plugins/smatrix/component_modelers/terminal.py (100%)
  • tidy3d/plugins/smatrix/data/terminal.py (100%)
  • tidy3d/plugins/smatrix/ports/base_terminal.py (100%)
  • tidy3d/plugins/smatrix/ports/coaxial_lumped.py (100%)
  • tidy3d/plugins/smatrix/ports/rectangular_lumped.py (100%)
  • tidy3d/plugins/smatrix/ports/wave.py (100%)
  • tidy3d/utils.py (100%)
  • tidy3d/web/api/tidy3d_stub.py (100%)

Summary

  • Total: 1153 lines
  • Missing: 21 lines
  • Coverage: 98%

tidy3d/components/geometry/utils.py

  653                 strict_bounds=strict_bounds,
  654                 margin=-snap_margin,
  655             )
  656             if max_snap < min_snap:
! 657                 raise SetupError("The supplied 'snap_margin' is too large for this contraction.")
  658         return (min_snap, max_snap)
  659 
  660     # Iterate over each axis and apply the specified snapping behavior.
  661     min_b, max_b = (list(f) for f in box.bounds)

tidy3d/components/microwave/base.py

  18         from tidy3d.config import config
  19 
  20         # Skip warning during test runs or when globally suppressed via config
  21         if not is_running_pytest() and not config.suppress_rf_license_warning:
! 22             log.warning(
  23                 "ℹ️ ⚠️ RF simulations are subject to new license requirements in the future. "
  24                 "You have instantiated at least one RF-specific component.",
  25                 log_once=True,
  26             )

tidy3d/components/microwave/path_integrals/factory.py

  128             v_integrals.append(None)
  129             i_integrals.append(None)
  130             continue
  131         elif isinstance(impedance_spec, AutoImpedanceSpec):
! 132             v_spec = None
! 133             i_spec = auto_spec.current_spec
  134         else:
  135             v_spec = impedance_spec.voltage_spec
  136             i_spec = impedance_spec.current_spec

tidy3d/components/microwave/path_integrals/integrals/base.py

  43     def compute_integral(self, scalar_field: EMScalarFieldType) -> IntegralResultType:
  44         """Computes the defined integral given the input ``scalar_field``."""
  45 
  46         if not scalar_field.does_cover(self.bounds, fp_eps, np.finfo(np.float32).smallest_normal):
! 47             raise DataError("Scalar field does not cover the integration domain.")
  48         coord = "xyz"[self.main_axis]
  49 
  50         scalar_field = self._get_field_along_path(scalar_field)
  51         # Get the boundaries

tidy3d/components/microwave/path_integrals/integrals/current.py

  191 
  192         # Perform phase splitting into in and out of phase for each frequency separately
  193         for term in path_currents:
  194             if np.all(term.abs == 0):
! 195                 continue
  196 
  197             # Compare phase to reference for each frequency
  198             phase_diff = term.angle - phase_reference
  199             # Wrap phase difference to [-pi, pi]

tidy3d/components/mode/mode_solver.py

  1385     ) -> tuple[tuple[Optional[VoltageIntegralType]], tuple[Optional[CurrentIntegralType]]]:
  1386         """Wrapper for making path integrals from the MicrowaveModeSpec. Note: overriden in the backend to support
  1387         auto creation of path integrals."""
  1388         if not self._has_microwave_mode_spec:
! 1389             raise ValueError(
  1390                 "Cannot make path integrals for when 'mode_spec' is not a 'MicrowaveModeSpec'."
  1391             )
  1392         return make_path_integrals(self.mode_spec)

  2025             )
  2026 
  2027         mode_solver_monitor_type = ModeMonitor
  2028         if self._has_microwave_mode_spec:
! 2029             mode_solver_monitor_type = MicrowaveModeMonitor
  2030 
  2031         return mode_solver_monitor_type(
  2032             center=self.plane.center,
  2033             size=self.plane.size,

tidy3d/plugins/microwave/auto_path_integrals.py

   1 """Backwards compatibility - import from tidy3d.components.microwave.path_integrals.integrals instead."""
   2 
   3 from __future__ import annotations
   4 
!  5 from tidy3d.components.microwave.path_integrals.integrals.auto import (
   6     path_integrals_from_lumped_element,
   7 )
   8 
!  9 __all__ = [
  10     "path_integrals_from_lumped_element",
  11 ]

tidy3d/plugins/microwave/custom_path_integrals.py

  1 """Backwards compatibility - import from tidy3d.components.microwave.path_integrals.integrals instead."""
  2 
  3 from __future__ import annotations
  4 
! 5 from tidy3d.components.data.data_array import (
  6     CurrentIntegralResultType,
  7     IntegralResultType,
  8     VoltageIntegralResultType,
  9     _make_base_result_data_array,

   9     _make_base_result_data_array,
  10     _make_current_data_array,
  11     _make_voltage_data_array,
  12 )
! 13 from tidy3d.components.microwave.path_integrals.integrals.base import (
  14     Custom2DPathIntegral,
  15 )
! 16 from tidy3d.components.microwave.path_integrals.integrals.current import (
  17     CompositeCurrentIntegral,
  18     Custom2DCurrentIntegral,
  19 )
! 20 from tidy3d.components.microwave.path_integrals.integrals.voltage import (
  21     Custom2DVoltageIntegral,
  22 )
  23 
! 24 __all__ = [
  25     "CompositeCurrentIntegral",
  26     "CurrentIntegralResultType",
  27     "Custom2DCurrentIntegral",
  28     "Custom2DPathIntegral",

tidy3d/plugins/microwave/impedance_calculator.py

  1 """Backwards compatibility - import from tidy3d.components.microwave instead."""
  2 
  3 from __future__ import annotations
  4 
! 5 from tidy3d.components.microwave.impedance_calculator import (
  6     CurrentIntegralType,
  7     ImpedanceCalculator,
  8     VoltageIntegralType,
  9 )

   7     ImpedanceCalculator,
   8     VoltageIntegralType,
   9 )
  10 
! 11 __all__ = [
  12     "CurrentIntegralType",
  13     "ImpedanceCalculator",
  14     "VoltageIntegralType",
  15 ]

tidy3d/plugins/microwave/path_integrals.py

   1 """Backwards compatibility - import from tidy3d.components.microwave.path_integrals.integrals instead."""
   2 
   3 from __future__ import annotations
   4 
!  5 from tidy3d.components.microwave.path_integrals.integrals.base import (
   6     AxisAlignedPathIntegral,
   7     EMScalarFieldType,
   8     IntegrableMonitorDataType,
   9 )
! 10 from tidy3d.components.microwave.path_integrals.integrals.current import (
  11     AxisAlignedCurrentIntegral,
  12 )
! 13 from tidy3d.components.microwave.path_integrals.integrals.voltage import (
  14     AxisAlignedVoltageIntegral,
  15 )
  16 
! 17 __all__ = [
  18     "AxisAlignedCurrentIntegral",
  19     "AxisAlignedPathIntegral",
  20     "AxisAlignedVoltageIntegral",
  21     "EMScalarFieldType",

Copy link
Collaborator

@weiliangjin2021 weiliangjin2021 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most went through code structures, and the structure looks in good shape. Some minor comments:

Copy link
Contributor

@dbochkov-flexcompute dbochkov-flexcompute left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very impressive work, finished the first pass and left some comments. Additionally, it seems like many new classes AxisAlignedPathIntegralSpec, CustomPathIntegral2DSpec, CurrentIntegralAxisAlignedSpec, CustomCurrentIntegral2DSpec, CompositeCurrentIntegralSpec, CustomImpedanceSpec, etc are missing examples in docstrings

@dmarek-flex dmarek-flex force-pushed the dmarek/add_impedance_to_mode_data branch from 7ad7a12 to 2727e2f Compare September 30, 2025 13:11
@dmarek-flex dmarek-flex added the rc2 2nd pre-release label Sep 30, 2025
@dmarek-flex dmarek-flex force-pushed the dmarek/add_impedance_to_mode_data branch from 917c3ad to d23f936 Compare September 30, 2025 17:52
@dmarek-flex
Copy link
Contributor Author

Thanks @dbochkov-flexcompute for finding those docstring mistakes. It was a little bit harder than expected to get doc tests running correctly because of the log warning we have for rf and microwave components. I got it working by introducing the MicrowaveBaseModel class. @daquinteroflex does this approach make sense for replacing the duplicated method for warning.

Copy link
Collaborator

@daquinteroflex daquinteroflex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks pretty good @dmarek-flex ! Just a few questions on very few API design considerations

@dmarek-flex dmarek-flex force-pushed the dmarek/add_impedance_to_mode_data branch 2 times, most recently from 837a080 to c685b6b Compare October 2, 2025 17:28
@dmarek-flex dmarek-flex added rc3 3rd pre-release and removed rc2 2nd pre-release labels Oct 7, 2025
@dmarek-flex dmarek-flex changed the title add impedance calculations to mode solver FXC-3517 add impedance calculations to mode solver Oct 7, 2025
@dmarek-flex dmarek-flex force-pushed the dmarek/add_impedance_to_mode_data branch 2 times, most recently from bee9d40 to 008ab9f Compare October 7, 2025 19:09
@dmarek-flex
Copy link
Contributor Author

Alright lets have another go @greptileai. Also since @daquinteroflex is away, can @tylerflex or @yaugenst-flex take a look at this refactoring of the MicrowaveModeSpec and monitors/monitor data

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Comments (1)

  1. tidy3d/plugins/microwave/auto_path_integrals.py, line 32-34 (link)

    logic: Parameter descriptions don't match parameter names - lumped_element and grid descriptions are incorrect

    Context Used: Rule from dashboard - Keep docstrings and comments synchronized with code changes to ensure they are always accurate and n... (source)

63 files reviewed, 9 comments

Edit Code Review Agent Settings | Greptile

@dmarek-flex dmarek-flex force-pushed the dmarek/add_impedance_to_mode_data branch 2 times, most recently from b2458d6 to 40bcc17 Compare October 8, 2025 14:29
@tylerflex
Copy link
Collaborator

tylerflex commented Oct 10, 2025

@dmarek-flex @weiliangjin2021

One question: all integral_specs are defined in component/microwave, but the actual integration computation is defined in plugin/microwave. Should we unify this by moving them from plugin to component?

We should figure out a plan regarding the RF/Tidy3D separation and organization long term.

@weiliangjin2021 just for a sense, here are some related discussions #2837 (comment)

My feeling is that the best long term solution is a complete separation of RF from the main tidy3d components. Meaning perhaps a tidy3d.rf namespace where all of the RF components, TerminalComponentModeler, microwave plugin, etc. can live.

But for this to be a reality, we would need to (at least):

  • Figure out how we want to extend tidy3d components / schemas to RF, eg. that ModeSpec discussion. Perhaps inheritance for start? with RF then having it's own schema that extends the tidy3d schema
  • Write the web API in a more generic way so we can easily extend it. Maybe using Protocol.
  • We may need dedicated web endpoints for RF, which we should eventually have but will be a bigger effort.

Could you guys think about this a bit in terms of requirements from your side and any preferences? @weiliangjin2021 let's discuss together with yannick and Lucas at the tech council meeting monday to get a general feeling because the same issues arise in photonforge.

@tylerflex
Copy link
Collaborator

I just started looking at this:

One idea occurred to me, which is that if we eventually do want to import rf components through a tidy3d.rf namespace, and this helps with organization, we could already create this namespace, eg tidy3d/rf/__init__.py that imports all RF related things directly, including TerminalComponentModeler. And then deprecate or leave out of the main tidy3d/__init__.py

While underlying things would still be all mixed without any changes, this would at least give us an ability to start crafting the user-facing side of the package.

note sure if worth doing here since this is a needed feature, but wanted to make a note.

@yaugenst-flex @daquinteroflex FYI

Copy link
Collaborator

@daquinteroflex daquinteroflex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we've decided to refactor this in a separate PR into tidy3d.rf, for now feel free to merge but won't be like this for rc3

Will do another review pass tomorrow my morning.

Copy link
Collaborator

@daquinteroflex daquinteroflex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just the few minor comments

@dmarek-flex dmarek-flex force-pushed the dmarek/add_impedance_to_mode_data branch 3 times, most recently from 27d9f00 to 9aa1b9b Compare October 15, 2025 13:56
@dmarek-flex
Copy link
Contributor Author

Just made some final tests with the deployed solver and everything looks good. I decided to submit the docs changes in a different PR so that we can take our time with that #2897

@dbochkov-flexcompute Let me know if you approve of the changes regarding the license warning.

@dmarek-flex dmarek-flex force-pushed the dmarek/add_impedance_to_mode_data branch from 9aa1b9b to 7a5edfc Compare October 15, 2025 16:09
@dmarek-flex dmarek-flex enabled auto-merge October 15, 2025 16:09
@dmarek-flex dmarek-flex added this pull request to the merge queue Oct 15, 2025
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Oct 15, 2025
add a ImpedanceSpec for controlling how characteristic impedance
 is calculated from modes

add MicrowaveModeMonitor and MicrowaveModeSolverMonitor that
 accepts the new MicrowaveModeSpec

BREAKING CHANGE: changed path integral class names in plugins/microwave
@dmarek-flex dmarek-flex force-pushed the dmarek/add_impedance_to_mode_data branch from 7a5edfc to c8f2694 Compare October 15, 2025 20:12
@dmarek-flex dmarek-flex enabled auto-merge October 15, 2025 20:12
@dmarek-flex dmarek-flex added this pull request to the merge queue Oct 15, 2025
Merged via the queue into develop with commit 86b4292 Oct 15, 2025
25 checks passed
@dmarek-flex dmarek-flex deleted the dmarek/add_impedance_to_mode_data branch October 15, 2025 21:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

rc3 3rd pre-release RF

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Automatic setup of path integrals

5 participants